package com.mic.yzzn.plc.core.ins.toolUtils;

import com.mic.yzzn.plc.core.plcevents.PLCFileChangeEvent;
import com.mic.yzzn.plc.core.plcevents.listener.PLCFileChangeEventListener;

import java.io.IOException;
import java.io.Serializable;
import java.nio.file.*;
import java.nio.file.WatchEvent.Kind;
import java.util.ArrayList;

/**
 * 用于监听某个目录文件改变的类
 */
public class PLCFileWatcher implements Runnable, Serializable
{
	/** 监听路径 */
	private String watchPath;
	/** 监听者列表 */
	private ArrayList<PLCFileChangeEventListener> listeners = new ArrayList<PLCFileChangeEventListener>();
	
	// 初始化方法
	@SuppressWarnings("unused")
	private PLCFileWatcher()
	{
		
	}
	
	public PLCFileWatcher(String path)
	{
		watchPath = path;
	}
	
	/**
	 * 开始监听指定目录
	 */
	public void startWatch()
	{
		new Thread(this).start();
	}
	
	/**
	 * Run方法
	 */
	@Override
	public void run()
	{
		Path dir = Paths.get(watchPath);
		
		try
		{
			// 取得监听服务
			WatchService watchService = FileSystems.getDefault().newWatchService();
			// 注册监听服务
			dir.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, 
					StandardWatchEventKinds.ENTRY_DELETE, 
					StandardWatchEventKinds.ENTRY_MODIFY);
			
			System.out.println("BeginWatch");
			
			while (true)
			{
				try
				{
					final WatchKey key = watchService.take();
					// 轮询文件事件
					for (WatchEvent<?> event : key.pollEvents())
					{
						Kind<?> kind = event.kind();
						
						// 文件改变事件
						PLCFileChangeEvent fileChangeEvent = null;
						
						if (kind == StandardWatchEventKinds.ENTRY_CREATE)
						{
							System.out.println("创建了新文件");
							System.out.println(event.context());
							fileChangeEvent = new PLCFileChangeEvent(this, 
									PLCFileChangeEvent.PLCFileChangeEventType.PLCFileChangeEventTypeCreate, 
									event.context().toString());
						}
						
						if (kind == StandardWatchEventKinds.ENTRY_MODIFY)
						{
							System.out.println("修改了以下文件");
							System.out.println(event.context());
							fileChangeEvent = new PLCFileChangeEvent(this, 
									PLCFileChangeEvent.PLCFileChangeEventType.PLCFileChangeEventTypeModified, 
									event.context().toString());
						}
						
						if (kind == StandardWatchEventKinds.ENTRY_DELETE)
						{
							System.out.println("删除了以下文件");
							System.out.println(event.context());
							fileChangeEvent = new PLCFileChangeEvent(this, 
									PLCFileChangeEvent.PLCFileChangeEventType.PLCFileChangeEventTypeDelete, 
									event.context().toString());
						}
						
						// 通知监听者
						if (!listeners.isEmpty() && event != null)
						{
							for (PLCFileChangeEventListener listener : listeners)
							{
								listener.notifyFileChange(fileChangeEvent);
							}
						}
						
						boolean valid = key.reset();
						
						if (!valid)
						{
							break;
						}
					}
				} 
				catch (InterruptedException e)
				{
					e.printStackTrace();
				}
			}
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 为文件改变事件添加监听者
	 * @param listener 监听者
	 */
	public void addListener(PLCFileChangeEventListener listener)
	{
		listeners.add(listener);
	}
	
	/**
	 * 为文件改变事件移除监听者
	 * @param listener 监听者
	 * @return 是否移除成功
	 */
	public boolean removeListener(PLCFileChangeEventListener listener)
	{
		return listeners.remove(listener);
	}
	
	// Getter
	public String getWatchPath()
	{
		return watchPath;
	};
}